using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
using SimpleSocket.Protocols;

namespace SimpleSocket
{
    public class Server
    {
        private readonly SocketListener _listener = null;
        private readonly IProtocol _protocol;
        private readonly ConcurrentDictionary<string, ConnectionInfo> _connPolls;

        public Server(IProtocol protocol, int port)
        {
            _protocol = protocol;
            _connPolls = new ConcurrentDictionary<string, ConnectionInfo>();
            this._listener = new SocketListener(new IPEndPoint(IPAddress.Any, port));
            this._listener.Accepted += ListenerOnAccepted;
        }

        private void ListenerOnAccepted(Socket obj)
        {
            var connection = new Connection(obj);
            if (obj.RemoteEndPoint is IPEndPoint remote)
                connection.RemoteIp = $"{remote.Address}:{remote.Port}";
            if (obj.LocalEndPoint is IPEndPoint local)
                connection.LocalIp = $"{local.Address}:{local.Port}";

            var connectionInfo = new ConnectionInfo(connection, new ClientSocket(_protocol, this));
            connectionInfo.BeginReceive();
            _connPolls.TryAdd(connection.RemoteIp, connectionInfo);
            
            Console.WriteLine($"新客户端已连接:{connection.RemoteIp}!");
        }
        
        /// <summary>
        /// start
        /// </summary>
        public void Start()
        {
            this._listener.Start();
        }
        /// <summary>
        /// stop
        /// </summary>
        public void Stop()
        {
            this._listener.Stop();
        }

        private class ClientSocket : Host
        {
            private readonly Server _server;

            public ClientSocket(IProtocol protocol, Server server) : base(protocol)
            {
                _server = server;
            }

            internal override void OnDisconnect(string remote, Exception error)
            {
                base.OnDisconnect(remote, error);
                _server._connPolls.TryRemove(remote, out _);
                Console.WriteLine($"客户端：{remote} 连接断开：OnDisconnect!");
            }

            protected override void OnConnectionChanged(string remote, bool success)
            {
                base.OnConnectionChanged(remote, success);
                if (!success)
                    _server._connPolls.TryRemove(remote, out _);
                
                Console.WriteLine($"客户端：{remote} 连接状态改变：{success}");
            }

            protected override void OnReceiveMessage(string remote, byte[] data)
            {
                base.OnReceiveMessage(remote, data);
                Console.WriteLine($"接收客户端消息：{remote} {Encoding.UTF8.GetString(data)}");
            }

            protected override void OnSendDataCallback(string remote, byte[] data, bool success)
            {
                base.OnSendDataCallback(remote, data, success);
                Console.WriteLine($"发送消息到客户端：{remote} {Encoding.UTF8.GetString(data)}");
            }
        }
    }
}